﻿/// <reference path = "Base.ts" />
namespace VantCellTypes {

    interface CalendarCellTypeParam {
        ClickCommand: Forguncy.Plugin.ICustomCommandObject;
        type: "single" | "multiple";
        DefaultValue: string;
        minDate: string;
        maxDate: string;
        showRangePrompt: boolean;
        maxRange: number;
        firstDayOfWeek: string;
        color: string;
        showMark: boolean;
        showSubtitle: boolean;
        allowSameDay: boolean;
        ReadOnly: boolean;
    }

    interface Day {
        date: Date;
        type: string;
        text: string;
        topInfo: string;
        bottomInfo: string;
        className: string;
    }

    export class CalendarCellType extends VantCellTypeBase<CalendarCellTypeParam> {
        public onPageLoaded(info: Forguncy.Plugin.CellTypeInfo) {
            const self = this;
            const cellType = this.cellType;
            const customFormatter = this.getCustomFeatureByPath(FeaturePath.calendarFormatter);
            const option = {
                template: `
<van-calendar
    ref="van-calendar"
    :show-title="false"
    :poppable="false"
    :type="type"
    :color="color"
    :min-date="minDate"
    :max-date="maxDate"
    :max-range="maxRange"
    :readonly="readonly"
    :show-confirm="false"
    :show-range-prompt="showRangePrompt"
    :first-day-of-week="firstDayOfWeek"
    :show-mark="showMark"
    :show-subtitle="showSubtitle"
    :allow-same-day="allowSameDay"
    @select="handleSelect"
    :formatter="formatter"
></van-calendar>
`,
                data() {
                    return {
                        cellValue: undefined,
                        ...cellType,
                        ...self.getDefaultData(cellType)
                    };
                },
                methods: {
                    setValue(value) {
                        this.cellValue = value;
                        let date;
                        if (typeof value === "number") {
                            date = Forguncy.ConvertOADateToDate(value);
                        } else if (typeof value === "string") {
                            date = [];
                            for (const item of value.split(",")) {
                                const oaDate = Number(item);
                                if (!isNaN(oaDate)) {
                                    date.push(Forguncy.ConvertOADateToDate(oaDate));
                                } else {
                                    const dateTime = DateUtil.ConvertToDate(item, null);
                                    if (dateTime !== null) {
                                        date.push(dateTime);
                                    } else {
                                        date = [];
                                        break;
                                    }
                                }
                            }
                        } else if (value instanceof Date) {
                            date = value;
                        } else {
                            date = new Date();
                        }
                        if (!Array.isArray(date) && this.type !== "single") {
                            date = [date];
                        }
                        if (this.lastDate) {
                            try {
                                if (this.lastDate instanceof Array && date instanceof Array) {
                                    if (this.lastDate.length === date.length) {
                                        if (date.every((item, index) => {
                                            return item?.valueOf() === this.lastDate[index]?.valueOf();
                                        })) {
                                            return;
                                        }
                                    }
                                }
                                else {
                                    if (this.lastDate?.valueOf() === date?.valueOf()) {
                                        return;
                                    }
                                }
                            }
                            finally {
                                this.lastDate = undefined;
                            }
                        }
                        this.$refs["van-calendar"].reset(date);
                    },
                    getValue() {
                        if (Array.isArray(this.cellValue)) {
                            return this.cellValue.join(",");
                        }
                        return this.cellValue;
                    },
                    setReadOnly(value: boolean) {
                        this.readonly = value;
                    },
                    handleSelect(date: Date | Date[]) {
                        if (cellType.ClickCommand?.Commands?.length) {
                            const initValue = {};
                            if (Array.isArray(date)) {
                                let result = null;
                                if (date.length > 0) {
                                    result = date[date.length - 1];
                                }
                                initValue[cellType.ClickCommand.ParamProperties["date"]] = result;
                            } else {
                                initValue[cellType.ClickCommand.ParamProperties["date"]] = date;
                            }
                            self.executeCustomCommandObject(cellType.ClickCommand, initValue);
                        }
                        if (Array.isArray(date)) {
                            this.cellValue = date.map((value: Date) => Forguncy.ConvertDateToOADate(value));
                        } else {
                            this.cellValue = Forguncy.ConvertDateToOADate(date);
                        }
                        this.lastDate = date;
                        self.commitValue();
                    },
                    formatter(day: Day) {
                        if (typeof customFormatter === "function") {
                            return customFormatter(day);
                        }
                        return day;
                    }
                }
            };

            this.createVueApp(option);

            this.onDependenceCellValueChanged(() => {
                this.vue.minDate = this.convertToDate(cellType.minDate);
                this.vue.maxDate = this.convertToDate(cellType.maxDate);
                this.vue.$nextTick(() => {
                    this.vue.setValue(this.vue.getValue());
                });
            });

            super.onPageLoaded(info);
        }

        private getDefaultData(cellType: CalendarCellTypeParam) {
            return {
                maxRange: this.isEmpty(cellType.maxRange) ? undefined : cellType.maxRange,
                readonly: false,
                showMark: !!cellType.showMark,
                showSubtitle: !!cellType.showSubtitle,
                allowSameDay: !!cellType.allowSameDay,
                showRangePrompt: !!cellType.showRangePrompt,
                minDate: this.convertToDate(cellType.minDate),
                maxDate: this.convertToDate(cellType.maxDate),
                color: Forguncy.ConvertToCssColor(cellType.color),
            };
        }

        private convertToDate(value: string) {
            return DateUtil.ConvertToDate(this.evaluateFormula(value), null) ?? undefined;
        }
    }
}

Forguncy.Plugin.CellTypeHelper.registerCellType("Vant.CellTypes.Calendar, Vant", VantCellTypes.CalendarCellType);